﻿using Autofac;
using Common;
using DBContext;
using EV.EventBus;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZoneLine.Common;
using ZoneLine.Models;
using ZoneLine.Models.PackageModel;
using ZoneLine.Printers;

namespace ZoneLine.Stations
{

    /// <summary>
    /// 
    /// </summary>
    /// <remarks>
    /// <para>上支撑螺母拧紧工位(左)</para>
    /// <para>StationCode：OP580-1 IP：192.168.10.90</para>
    /// </remarks>
    public class QOP050LStation : WorkStationDBase
    {
        public QOP050LStation()
        {
        }

        public string CurrentProductType { get; set; }

        public void Init(string ip, int port, string startAddr, string endUploadCodeAddr, string endUploadDataAddr, string allowWorkAddr, string printName)
        {
            Ip = ip;
            Port = port;
            _startAddr = startAddr;
            _readLength = 1036;
            _printerName = printName;
            //StationCode = "OP580";
            StationCode = "OP580-1";
            EndUpLoadCodeAddr = endUploadCodeAddr;
            EndUpLoadDataAddr = endUploadDataAddr;
            AllowWorkAddr = allowWorkAddr;
            StationRecordData = new QOP050LStationResult();
            HeartToPlcAddr = "DB1001.0";
            PrintRltAddr = "DB1001.518";

            ResetPrintTriggerAddr = "DB1001.12";

            _logUiChannel = CurrentStationName + "uilog";

            WorkDirectionAddr = "DB1001.14";

            CurrentProductType = "DB1001.2168";

            //TaskMaster.Default.AddCycleTask(nameof(QOP050LStation), 1, () =>
            //{
            //    #region 不在需要下发了，下发配方的时候下位机自行判断
            //    ////var value = (short)Cache.WorkDirection;
            //    ////WriteData(WorkDirectionAddr, value);
            //    ////_client?.Write(CurrentProductType, Cache.CurrentProductType);
            //    #endregion
            //}, false, EV.EventBus.CycleTask.TimeBaseEnum._1S);

            MessageCenter.Subscribe(nameof(QOP050LStation), nameof(QOP050LStation), (e) =>
            {
                PrintLabel(false);
                return Task.CompletedTask;
            });

            base.InitReSetAddr();
        }

        private QOP050LStationResult _stationRecordData;

        public QOP050LStationResult StationRecordData
        {
            get { return _stationRecordData; }
            set => SetProperty(ref _stationRecordData, value);
        }

        private string _printerName;

        private short _triggerPrint;

        /// <summary>
        /// 触发打印
        /// </summary>
        public short TriggerPrint
        {
            get { return _triggerPrint; }
            set => SetProperty(ref _triggerPrint, value);
        }

        private int _index;

        /// <summary>
        /// 生产流水号
        /// </summary>
        public int Index
        {
            get { return _index; }
            set => SetProperty(ref _index, value);
        }

        private short _handSignalPrint;

        public short HandSignalPrint
        {
            get { return _handSignalPrint; }
            set { _handSignalPrint = value; }
        }

        public string WorkDirectionAddr { get; set; }

        /// <summary>
        /// 打印结论plc地址
        /// </summary>
        public string PrintRltAddr { get; set; }

        public string ResetPrintTriggerAddr { get; private set; }

        protected override void DealData(byte[] content)
        {
            StationRecordData.AbsScanCode = GetPlcString(content, 280);
            StationRecordData.NutScanCode = GetPlcString(content, 322);
            StationRecordData.PartType = GetPlcString(content, 1002);
            StationRecordData.Result = _client.ByteTransform.TransInt16(content, 1000).ToString().Equals("1") ? "OK" : "NG";
            StationRecordData.TightenTorque = _client.ByteTransform.TransSingle(content, 1016);
            StationRecordData.TightenAngle = _client.ByteTransform.TransSingle(content, 1020);
            StationRecordData.CycleTime = _client.ByteTransform.TransSingle(content, 1032);
            StationRecordData.ThreadLength = _client.ByteTransform.TransSingle(content, 1024);

            TriggerPrint = _client.ByteTransform.TransInt16(content, 500);

            HandSignalPrint = _client.ByteTransform.TransInt16(content, 506);

            //不再使用plc中的流水号，使用软件自动生成流水号
            //Index = _client.ByteTransform.TransInt16(content, 504);
        }

        protected override void DealWithSignal(string name)
        {
            if (name == nameof(StartUploadCode))
            {
                //todo 上传了条码 这时候验证是否要工作
                if (StartUploadCode == false)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到上传条码命令变为false", StationRecordData.AbsScanCode);
                    WriteData(EndUpLoadCodeAddr, 0, StationRecordData.AbsScanCode);
                    WriteData(AllowWorkAddr, 0, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}复位工作控制指令和复位上传条码完成指令", StationRecordData.AbsScanCode);

                    WriteData(PrintRltAddr, 0, StationRecordData.AbsScanCode);//清空PLC打标标记
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打标记录,clear", StationRecordData.AbsScanCode);
                    return;
                }
                else
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到上传条码信息命令", StationRecordData.AbsScanCode);

                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位结论验证,条码信息是{StationRecordData.AbsScanCode}", StationRecordData.AbsScanCode);
                    var validataRlt = Validata(CurrentStationName, StationRecordData.AbsScanCode, new string[] { "QOP050RStation" });
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位的验证结果是{validataRlt}", StationRecordData.AbsScanCode);
                    var writeRlt = WriteWorkActionToPlc(AllowWorkAddr, validataRlt, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位向下位机下发消息,下发{writeRlt}", StationRecordData.AbsScanCode);
                    return;
                }
            }

            if (name == nameof(StartUploadData))
            {
                if (StartUploadData)
                {
                    //todo 上传数据 这时候将数据记录到数据库中
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到上传记录数据命令", StationRecordData.AbsScanCode);
                    var rlt = RecordData();
                    WriteData(EndUpLoadDataAddr, (short)rlt, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}数据记录,rlt={rlt}", StationRecordData.AbsScanCode);
                    if (StationRecordData.Result == _okCode && rlt == 1)
                    {
                        LogWithUi(_logUiChannel, $"在{CurrentStationName}数据记录完成,打印标签开始1", StationRecordData.AbsScanCode);
                        PrintLabel();
                        LogWithUi(_logUiChannel, $"在{CurrentStationName}数据记录完成,打印标签完成1", StationRecordData.AbsScanCode);
                    }
                }
                else
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到上传记录数据命令变为false", StationRecordData.AbsScanCode);

                    WriteData(EndUpLoadDataAddr, 0, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}数据记录,clear", StationRecordData.AbsScanCode);
                }
            }

            if (name == nameof(TriggerPrint))
            {
                if (TriggerPrint == 1 && HandSignalPrint == 0)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}记录数据完成,打印标签开始2", StationRecordData.AbsScanCode);
                    PrintLabel();
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}记录数据完成,打印标签完成2", StationRecordData.AbsScanCode);
                }
                else
                {
                    // WriteData(PrintRltAddr, 0);
                }
                return;
            }
        }

        private void PrintLabel(bool needInc = true)
        {
            //Index = ProductIndexHelper.GetIndex(Cache.Model, 0, Cache.WorkDirection, WorkDirectionEnum.Left, needInc);
            Index = CheckCodeExists(needInc);

            WriteData(ResetPrintTriggerAddr, 1);
            LogWithUi(_logUiChannel, $"在{CurrentStationName}收到打印信息，打印第{Index}号工件", StationRecordData.AbsScanCode);
            IPrinter printer = null;
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var templatePath = string.Empty;
            switch (Cache.Model)
            {
                case ModelEnum.LX:
                    printer = new LXQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.LxqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.LxqcConfig.TemplatePathR;
                    }
                    break;

                case ModelEnum.SQ:
                    printer = new SQQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.Sqqc_Config.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.Sqqc_Config.TemplatePathR;
                    }
                    break;

                case ModelEnum.BQKH:
                    printer = new BQKHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcKhConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcKhConfig.TemplatePathR;
                    }
                    break;

                case ModelEnum.BQLH:
                    printer = new BQLHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.BqqcLHConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.BqqcLHConfig.TemplatePathR;
                    }
                    break;

                case ModelEnum.WL:
                    printer = new WLQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left)
                    {
                        templatePath = config.WlqcConfig.TemplatePath;
                    }
                    else
                    {
                        templatePath = config.WlqcConfig.TemplatePathR;
                    }
                    break;

                default:
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到不存在对应的模板，打印失败", StationRecordData.AbsScanCode);
                    break;
            }
            if (printer != null)
            {
                try
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始打印第【{Index}】工件，模板是【${templatePath}】", StationRecordData.AbsScanCode);
                    var code = printer.PrintLabel(templatePath, _printerName, Index);
                    //打印成功，将数据打印的数据记录到关联表中
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印第{Index}工件、工件abs码【{StationRecordData.AbsScanCode}】完成", StationRecordData.AbsScanCode);
                    var printRecord = new AbsPrintResult();
                    printRecord.Brand = Cache.Model.ToString();
                    printRecord.AbsCode = StationRecordData.AbsScanCode;
                    printRecord.Code = code;
                    printRecord.PrintTime = DateTime.Now;
                    var para = StationEnableConfig.GetPara();
                    printRecord.LeftRight = (int)Cache.WorkDirection;
                    _dal.AddModel(printRecord);
                    _dal.UpdateModel<QOP050LStationResult>(p => p.AbsScanCode == printRecord.AbsCode, p => new QOP050LStationResult { Code = code });
                    UpdateBeforeStationCode(printRecord.AbsCode, code);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始发送{PrintRltAddr}点位数据，值为{1}", StationRecordData.AbsScanCode);
                    var res = WriteData(PrintRltAddr, 1);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始发送{PrintRltAddr}点位数据，值为{1}，res={res}", StationRecordData.AbsScanCode);
                }
                catch (Exception ex)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印失败,失败原因{ex.Message}", StationRecordData.AbsScanCode);
                    WriteData(PrintRltAddr, 2);
                }
            }
        }

        protected override int RecordData()
        {
            var result = StationRecordData;
            result.CreateTime = DateTime.Now;
            var writeRlt = false;
            if (_dal.CheckExist<QOP050LStationResult>(p => p.AbsScanCode == result.AbsScanCode))
            {
                var beforeRlt = _dal.GetModel<QOP050LStationResult>(p => p.AbsScanCode == result.AbsScanCode);
                result.Id = beforeRlt.Id;
                writeRlt = _dal.UpdateModelSuper<QOP050LStationResult>(p => p.AbsScanCode == result.AbsScanCode, result);
            }
            else
            {
                writeRlt = _dal.AddModel(result);
            }
            return writeRlt ? 1 : 2;
        }


        public int CheckCodeExists(bool needInc)
        {
            var dal = ContainerServer.Container.Resolve<IModelDAL>();
            var index = ProductIndexHelper.GetIndex(Cache.Model, 0, Cache.WorkDirection, WorkDirectionEnum.Left, needInc);
            if (Cache.Model == ModelEnum.LX)
            {
                var code = LXQCPrinter.GetLableBarCode(index);
                var exists = dal.CheckExist<QOP050LStationResult>(p => p.Code == code);
                if (exists)
                {
                    Logger.Log.Info($"产品{StationRecordData.AbsScanCode},生成码:{code},已存在");
                    return CheckCodeExists(needInc);
                }
            }
            return index;
        }

    }
}